package com.example.springboot.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.example.springboot.dto.BloodValueTableDTO;
import com.example.springboot.dto.SamplingFrequencyDTO;
import com.example.springboot.entity.AlarmTable;
import com.example.springboot.entity.BloodValueTable;
import com.example.springboot.entity.ParameterTable;
import com.example.springboot.service.IAlarmTableService;
import com.example.springboot.service.IBloodValueTableService;
import com.example.springboot.service.IParameterTableService;
import com.example.springboot.vo.BloodValueTableVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/bloodPressure")
@Slf4j
@Api(value = "", tags = "蓝牙数据")
@RequiredArgsConstructor
@ConfigurationProperties(prefix = "export.data")
public class BloodPressureController {

    private final IBloodValueTableService iBloodValueTableService;
    private final IParameterTableService iParameterTableService;
    private final IAlarmTableService iAlarmTableService;
    @Value("${export.data.file-path}")
    private String filePath;
    @Value("${export.data.domain-url}")
    private String domainUrl;
    @PostMapping("/update")
    @ApiOperation(value = "数据上报", notes = "血压数据上报")
    public R<BloodValueTableDTO>  updateInstruct(@ApiParam(value = "设备编号", required = true) @RequestParam String deviceId,
                                                 @ApiParam(value = "指令", required = true) @RequestParam String instruct) {
        log.info("接受到的消息为:{}",deviceId);
        String substring = instruct.substring(2, 4);
        if(!substring.equalsIgnoreCase("03")){
            return R.failed("数据上报错误");
        }
        String hexString = instruct.substring(4, 12);
        long conver1 = Long.parseLong(hexString, 16);
        float conver = (float) (conver1 * 40000000L) / 268435456.0f;
        if(conver!=0.0){
            conver *= 2.0f * 3.1415926f;
            conver = 1.0f / ((conver * conver) * 0.000018f);
            conver -= 0.000000000033f;
            conver *= 1000000000000f;
        }

        log.info("血压为:{}",conver);
        BloodValueTable bloodValueTable = new BloodValueTable();
        ParameterTable one = iParameterTableService.getOne(Wrappers.<ParameterTable>lambdaQuery().eq(ParameterTable::getDeviceId,deviceId));
        String format =null;
        Boolean salarm = false;
        Double alarmValue = 0.0;
        if(one!=null){
            if(one.getValue1()!=null&&one.getValue2()!=null){
                double v = one.getValue1() + one.getValue2() * conver;
                format = String.format("%.4f", v);
                bloodValueTable.setBloodValue(Float.parseFloat(format));
                if(one.getValue3()!=null){
                    float v1 = Float.parseFloat(format);
                    if(one.getValue3()>v1){
                        AlarmTable alarmTable = new AlarmTable();
                        alarmTable.setAlarmValue(one.getValue3()+"");
                        alarmTable.setCreateTime(LocalDateTime.now());
                        alarmTable.setBloodValue(v1);
                        alarmTable.setDeviceId(deviceId);
                        iAlarmTableService.save(alarmTable);
                        salarm = true;
                        alarmValue = one.getValue3();
                    }

                }

            }

        }
        bloodValueTable.setCapacitancValue(conver);
        bloodValueTable.setCreateTime(new Date());
        bloodValueTable.setDeviceId(deviceId);
        iBloodValueTableService.save(bloodValueTable);
        List<BloodValueTable> list = iBloodValueTableService.list(Wrappers.<BloodValueTable>lambdaQuery()
                .eq(BloodValueTable::getDeviceId,deviceId).orderByDesc(BloodValueTable::getCreateTime).last("LIMIT 15"));
        if(!CollectionUtils.isEmpty(list)){
            Double finalAlarmValue = alarmValue;
            return R.ok(BloodValueTableDTO.builder().capacitancValue(conver).isAlarm(salarm)
                    .bloodValue(format)
                    .bloodValueTables(list.stream().map(x->{
                        BloodValueTableVO bloodValueTableVO  = new BloodValueTableVO();
                        bloodValueTableVO.setAlarmValue(finalAlarmValue);
                        bloodValueTableVO.setCapacitancValue(x.getCapacitancValue());
                        bloodValueTableVO.setBloodValue(x.getBloodValue());
                        bloodValueTableVO.setDeviceId(x.getDeviceId());
                        bloodValueTableVO.setCreateTime(x.getCreateTime());
                        return bloodValueTableVO;
                    }).sorted(Comparator.comparing(BloodValueTableVO::getCreateTime)).collect(Collectors.toList())).build());
        }
        return R.ok(null);
    }
    @GetMapping("/excel")
    @ApiOperation(value = "设备采集数据导出 ", notes = "设备采集数据导出")
    public R<String> lineChart(@RequestParam(value = "deviceId") String deviceId,
                                              @RequestParam(value = "startTime") Long startTime,
                                              @RequestParam(value = "endTime") Long endTime) {
        if(startTime.equals(endTime)){
            endTime=endTime+(1000*60*60*24)-1;
        }
        List<BloodValueTable> list = iBloodValueTableService.list(Wrappers.<BloodValueTable>lambdaQuery()
                .eq(BloodValueTable::getDeviceId,deviceId).between(BloodValueTable::getCreateTime,new Date(startTime),new Date(endTime)));
        if(CollectionUtils.isEmpty(list)){
            return R.failed("当前设备暂无数据");
        }
        String format = DateUtils.format(new Date(),"yyyy-MM-dd");
        String exportPath = filePath.concat("/").concat(format).concat("/");
        File file =new File(exportPath);
        if (!file.exists()) {
            file.mkdir();
        }
        String fileName=DateUtils.format(new Date(),"yyyyMMddHHmmss").concat("采集数据.xlsx");
        String newFileData = exportPath.concat(fileName);
        EasyExcel.write(newFileData,BloodValueTable.class).sheet(format.concat("采集数据.xlsx")).doWrite(list);
        return R.ok(domainUrl.concat(format).concat("/").concat(fileName));
    }
    @PostMapping("/setSamplingFrequency")
    @ApiOperation(value = "设置采样频率", notes = "设置采样频率")
    public R<SamplingFrequencyDTO> setSamplingFrequency(@ApiParam(value = "频率", required = true) @RequestParam Integer frequency) {
        frequency =  frequency * 1000;
        Integer data1 = frequency >> 8; // 右移8位，将低8位舍弃，保留高8位即为Data1的值
        // 恢复Data2
        Integer data2 = frequency & 0xFF; // 对combinedValue进行按位与0xFF(即十进制的255，二进制的11111111)，只保留最低8位即为Data2的值
        String s1 = "6801" + String.format("%02X", data1) + String.format("%02X", data2) + "16";
        return R.ok( SamplingFrequencyDTO.builder().frequency(byteArrayToByteList(hexStringToByteArray(s1)))
                .startCollecting(byteArrayToByteList(hexStringToByteArray("6802000016")))
                 .stopCollection(byteArrayToByteList(hexStringToByteArray("6802000116"))).build());
    }

    @PostMapping("/setParameterTable")
    @ApiOperation(value = "设置参数", notes = "设置参数")
    public R<ParameterTable> setParameterTable(@ApiParam(value = "参数1", required = true) @RequestParam Double value1,
                                               @ApiParam(value = "设备编号", required = true) @RequestParam String deviceId,
                                               @ApiParam(value = "参数2", required = true) @RequestParam Double value2,
                                                @ApiParam(value = "告警", required = false) @RequestParam Double value3) {
        ParameterTable one = iParameterTableService.getOne(Wrappers.lambdaQuery());
        if(one==null){
            ParameterTable parameterTable = new ParameterTable();
            parameterTable.setValue1(value1);
            parameterTable.setValue2(value2);
            parameterTable.setValue3(value3);
            parameterTable.setDeviceId(deviceId);
            iParameterTableService.save(parameterTable);
            return R.ok(parameterTable);
        }else {
            one.setValue1(value1);
            one.setValue2(value2);
            one.setValue3(value3);
            one.setDeviceId(deviceId);
            iParameterTableService.updateById(one);
            return R.ok(one);
        }

    }
    @GetMapping("/getParameterTable")
    @ApiOperation(value = "设置参数", notes = "设置参数")
    public R<ParameterTable> getParameterTable(@RequestParam(value = "deviceId") String deviceId) {
        return R.ok(iParameterTableService.getOne(Wrappers.<ParameterTable>lambdaQuery().eq(ParameterTable::getDeviceId,deviceId)));
    }
    public static List<Byte> byteArrayToByteList(byte[] byteArray) {
        List<Byte> byteList = new ArrayList<>();
        for (byte b : byteArray) {
            byteList.add(b);
        }
        return byteList;
    }
    public static byte[] hexStringToByteArray(String hexString) {
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("Invalid hexadecimal string: must have an even number of characters");
        }
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < byteArray.length; i++) {
            String hexPair = hexString.substring(i * 2, i * 2 + 2);
            byteArray[i] = (byte) Integer.parseInt(hexPair, 16);
        }
        return byteArray;
    }
}
